﻿using System;
using System.Windows;
using System.Windows.Input;

namespace WpfApp1
{
    /// <summary>
    /// Window1.xaml 的交互逻辑
    /// </summary>
    public partial class Window1 : Window
    {
        private bool _Move;
        private Point _ClickStartPoint;
        private Point _TransPoint;      //平移
        private double _CurrentScale = 1.0;   //当前缩放比例
        public Window1()
        {
            InitializeComponent();
        }
        private void myControl_MouseDown(object sender, MouseButtonEventArgs e)
        {
            _Move = true;

            var mousePos = e.GetPosition(scrollViewer);
            if (mousePos.X <= scrollViewer.ViewportWidth
                && mousePos.Y <= scrollViewer.ViewportHeight)
            {
                scrollViewer.Cursor = Cursors.Hand;
                _TransPoint = new Point(translateTransform.X, translateTransform.Y);
                _ClickStartPoint = e.GetPosition(scrollViewer);
                Console.WriteLine(_ClickStartPoint);
            }
            e.Handled = true;
        }

        private void myControl_MouseUp(object sender, MouseButtonEventArgs e)
        {
            _Move = false;
            scrollViewer.Cursor = Cursors.Arrow;
        }

        private void scrollViewer_MouseMove(object sender, MouseEventArgs e)
        {
            if (_Move && e.LeftButton == MouseButtonState.Pressed)
            {
                Point currentPoint = e.GetPosition(scrollViewer);
                translateTransform.X = _TransPoint.X + (currentPoint - _ClickStartPoint).X;
                translateTransform.Y = _TransPoint.Y + (currentPoint - _ClickStartPoint).Y;
                Console.WriteLine(currentPoint);
                double newX = translateTransform.X;
                double newY = translateTransform.Y;

                ApplyTranslationBounds(ref newX, ref newY);

                translateTransform.X = newX;
                translateTransform.Y = newY;
            }
            Console.WriteLine(scrollViewer.IsMouseCaptured);
            e.Handled = true;
        }

        private void ApplyTranslationBounds(ref double newX, ref double newY, double? scale = null)
        {
            double actualScale = scale ?? _CurrentScale;
            double scaledWidth = image.ActualWidth * actualScale;
            double scaledHeight = image.ActualHeight * actualScale;

            double viewportWidth = scrollViewer.ViewportWidth;
            double viewportHeight = scrollViewer.ViewportHeight;

            // X轴边界检查
            if (scaledWidth > viewportWidth)
            {
                // 图像比视口宽，限制左右边界
                newX = Math.Min(0, newX); // 不能右移超出边界
                newX = Math.Max(viewportWidth - scaledWidth, newX); // 不能左移超出边界
                Console.WriteLine("超出");
            }
            else
            {
                // 图像比视口窄，居中显示
                newX = (viewportWidth - scaledWidth) / 2;
                Console.WriteLine("居中");
            }

            // Y轴边界检查
            if (scaledHeight > viewportHeight)
            {
                // 图像比视口高，限制上下边界
                newY = Math.Min(0, newY); // 不能下移超出边界
                newY = Math.Max(viewportHeight - scaledHeight, newY); // 不能上移超出边界
            }
            else
            {
                // 图像比视口矮，居中显示
                newY = (viewportHeight - scaledHeight) / 2;
            }
        }
        // 获取当前图像边界（考虑缩放）
        private Rect GetImageBounds(double? scale = null)
        {
            double actualScale = scale ?? _CurrentScale;
            double width = image.ActualWidth * actualScale;
            double height = image.ActualHeight * actualScale;
            return new Rect(0, 0, width, height);
        }
        private void myControl_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            _Move = false;
            Point mousePos = e.GetPosition(image);
            double zoomRate = 1.1;
            if (e.Delta < 0)
                zoomRate = 1 / zoomRate;

            Zoom(mousePos, zoomRate);
        }

        private void Zoom(Point mousePoint, double zoomRate)
        {
            // 限制缩放范围
            const double MinScale = 0.9;
            const double MaxScale = 5.0;

            double newScale = _CurrentScale * zoomRate;

            if (newScale >= MaxScale)
                return;

            newScale = Math.Max(MinScale, Math.Min(MaxScale, newScale));

            //计算缩放后的坐标转换
            Vector relative = mousePoint - new Point(translateTransform.X, translateTransform.Y);
            Vector delta = (relative * zoomRate) - relative;
            // 计算新的平移位置
            double newX = translateTransform.X - delta.X;
            double newY = translateTransform.Y - delta.Y;

            ApplyTranslationBounds(ref newX, ref newY, newScale);


            scaleTransform.ScaleX = newScale;
            scaleTransform.ScaleY = newScale;
            translateTransform.X = newX;
            translateTransform.Y = newY;

            _CurrentScale = newScale;
        }

        private void myControl_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingEventArgs e)
        {

        }

        private void myControl_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
        {
            // 处理缩放
            if (e.DeltaManipulation.Scale.X != 0 || e.DeltaManipulation.Scale.Y != 0)
            {
                Point center = e.ManipulationOrigin;
                double scaleFactor = (e.DeltaManipulation.Scale.X + e.DeltaManipulation.Scale.Y) / 2;
                Zoom(center, scaleFactor);
            }

            // 处理平移
            Vector translation = e.DeltaManipulation.Translation;
            if (translation.X != 0 || translation.Y != 0)
            {
                double newX = translateTransform.X + translation.X;
                double newY = translateTransform.Y + translation.Y;

                //应用边界限制
                ApplyTranslationBounds(ref newX, ref newY);

                translateTransform.X = newX;
                translateTransform.Y = newY;
            }
        }

        private void myControl_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
        {

        }
    }
}
